Terminal Command Security - Tenant Configuration
Overview
The ATOM SaaS platform provides tenant-configurable terminal command security to ensure safe execution of terminal skills while allowing customization based on tenant needs and plan tiers.
Features
- **Per-Tenant Configuration**: Each tenant can customize their terminal security settings
- **Platform Defaults**: Hardcoded fallbacks ensure security even if database config is missing
- **Tier-Based Permissions**: Higher tiers get additional commands automatically
- **Security Modes**: Restrictive, permissive, or custom modes
- **Caching**: In-memory cache with 1-minute TTL for performance
- **Audit Logging**: All configuration changes logged to audit_logs table
Security Model
Platform Defaults
**Whitelist Commands** (14 commands):
ls,pwd,echo,cat,grep,findnode,python3,python,npmgit,docker,head,tail,wc
**Blacklist Commands** (16 commands):
rm,rmdir,mv,cp,chmod,chowndd,mkfs,fdisk,kill,killallsudo,su,nc,netcat,curl,wget
Tier-Based Bonuses
| Tier | Bonus Commands | Description |
|---|---|---|
| Free | None | Platform defaults only |
| Solo | curl, wget, rsync, ssh | Removed from blacklist, added to whitelist |
| Team | curl, wget, rsync, ssh | Additional network tools |
| Enterprise | No blacklist | Can override platform defaults (blacklist empty) |
Security Modes
| Mode | Whitelist Behavior | Blacklist Behavior |
|---|---|---|
| Restrictive | **Enforced** - only whitelist commands allowed | **Always enforced** - blocked commands always denied |
| Permissive | Not enforced - any command allowed | **Always enforced** - blocked commands always denied |
| Custom | Tenant-defined behavior | Tenant-defined behavior |
API Endpoints
GET /api/admin/terminal-security
Get tenant's current terminal security configuration.
**Required Role**: super_admin, admin, workspace_admin
**Response**:
{
"tenant_id": "uuid",
"tier": "team",
"whitelist": ["ls", "pwd", "echo", "cat", "grep", "find", "node", "python3", "python", "npm", "git", "docker", "head", "tail", "wc"],
"blacklist": ["rm", "rmdir", "mv", "cp", "chmod", "chown", "dd", "mkfs", "fdisk", "kill", "killall", "sudo", "su", "nc", "netcat", "curl", "wget"],
"mode": "restrictive",
"timeout": 30000
}PATCH /api/admin/terminal-security
Update tenant's terminal security configuration.
**Required Role**: super_admin, admin, workspace_admin
**Request Body**:
{
"whitelist": ["ls", "pwd", "echo", "cat"], // Optional: array of command names
"blacklist": ["rm", "mv", "chmod"], // Optional: array of command names
"mode": "permissive", // Optional: "restrictive" | "permissive" | "custom"
"timeout": 60000 // Optional: 1000-300000ms (5 minutes max)
}**Validation Rules**:
- Commands must be alphanumeric (a-z, A-Z, 0-9, -, _)
- Whitelist cannot be empty in restrictive mode
- Timeout must be between 1000ms and 300000ms
- Mode must be one of: restrictive, permissive, custom
**Response**:
{
"success": true,
"updated": ["whitelist", "mode"]
}DELETE /api/admin/terminal-security
Reset tenant's terminal security to platform defaults.
**Required Role**: super_admin only
**Response**:
{
"success": true,
"message": "Terminal security settings reset to platform defaults"
}Usage Examples
Example 1: Get Current Settings
const response = await fetch('/api/admin/terminal-security', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const settings = await response.json();
console.log('Current mode:', settings.mode);
console.log('Allowed commands:', settings.whitelist);Example 2: Add Command to Whitelist
const response = await fetch('/api/admin/terminal-security', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
whitelist: ['ls', 'pwd', 'echo', 'cat', 'grep', 'find', 'jq'] // Add jq command
}
});
const result = await response.json();
console.log('Updated:', result.updated);Example 3: Switch to Permissive Mode
const response = await fetch('/api/admin/terminal-security', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
mode: 'permissive'
}
});Example 4: Increase Command Timeout
const response = await fetch('/api/admin/terminal-security', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
timeout: 60000 // 60 seconds
}
});Example 5: Reset to Defaults (Super Admin Only)
const response = await fetch('/api/admin/terminal-security', {
method: 'DELETE'
});
const result = await response.json();
console.log(result.message);Security Guarantees
Blacklist Always Wins
The blacklist is checked **before** the whitelist in all modes. This ensures dangerous commands are always blocked regardless of mode or tier.
**Exception**: Enterprise tier has no blacklist restrictions.
Platform Defaults Exist
Even if the database is missing or corrupted, hardcoded platform defaults ensure security:
- Whitelist: 14 safe commands
- Blacklist: 16 dangerous commands
- Mode: restrictive
- Timeout: 30000ms
Audit Trail
All configuration changes are logged to audit_logs table:
- Who made the change (user_id)
- What changed (updated fields)
- When (timestamp)
- Tenant context
Role-Based Access
- **View Settings**: super_admin, admin, workspace_admin
- **Update Settings**: super_admin, admin, workspace_admin
- **Reset to Defaults**: super_admin only
Database Schema
tenant_settings Table
CREATE TABLE tenant_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
setting_key VARCHAR(255) NOT NULL,
setting_value TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(tenant_id, setting_key)
);Setting Keys
| Key | Type | Example Value |
|---|---|---|
terminal_command_whitelist | JSON | ["ls","pwd","echo"] |
terminal_command_blacklist | JSON | ["rm","mv","chmod"] |
terminal_security_mode | String | restrictive |
terminal_command_timeout_ms | Integer | 30000 |
Migration
To apply the database migration:
cd backend-saas
alembic upgrade headThis will:
- Create
tenant_settingstable (if not exists) - Populate platform defaults for all existing tenants
- Ensure all tenants have terminal security configuration
Testing
Unit Tests
npm test -- terminal-security.test.tsIntegration Tests
npm test -- route.test.tsE2E Tests
npm run test:e2eTroubleshooting
Issue: Commands Not Allowed
**Symptom**: Agent fails with "Security Block: Command 'X' is not in the allowed whitelist"
**Solution**:
- Check tenant settings:
GET /api/admin/terminal-security - Add command to whitelist if appropriate
- Or switch to permissive mode (allows all except blacklist)
Issue: Cache Staleness
**Symptom**: Changes to settings not taking effect immediately
**Solution**: Cache automatically invalidates after 1 minute. For immediate effect:
- Restart the application server
- Or wait 60 seconds for cache expiry
Issue: Migration Fails
**Symptom**: alembic upgrade head fails with "relation does not exist"
**Solution**: Ensure PostgreSQL is running and DATABASE_URL is correctly set in .env:
# Check database connection
psql $DATABASE_URL -c "SELECT 1"
# Run migration
cd backend-saas && alembic upgrade headBest Practices
- **Start Restrictive**: Use restrictive mode for new tenants
- **Audit Changes**: Review audit_logs regularly for security policy changes
- **Tier Upgrades**: When upgrading tenants, inform them of new command permissions
- **Timeout Limits**: Set reasonable timeouts to prevent runaway commands
- **Command Validation**: Always validate command names (alphanumeric only)
Security Considerations
- **Command Injection**: Arguments are sanitized to prevent command injection
- **Privilege Escalation**: sudo and su always blacklisted (except enterprise)
- **Data Destruction**: rm, dd, mkfs always blacklisted (except enterprise)
- **Network Access**: curl, wget, rsync, ssh restricted by tier (available solo+)
- **Timeout Protection**: All commands timeout after configured duration
Future Enhancements
Potential improvements:
- Command execution logging (which commands were run)
- Per-agent security policies (more granular than tenant-level)
- Time-based restrictions (limit command execution to business hours)
- Resource limits (CPU, memory per command)
- Command approval workflows (require admin approval for new commands)